﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AccesoBD;
using System.Data.SqlClient;
using CapaLogica.CL.Carrera;
using System.Data;
using CapaLogica.CL.UtilidadesGenerales;
using CapaLogica.CL.Bitacora;
using CapaLogica.CL.Usuario;



namespace CapaLogica
{
    public class CursoPersistente
    {
        private AcessoBD _acceso = new AcessoBD();

        /// <summary>
        /// Método de la clase encargada de insertar un nuevo Curso a la DB 
        /// </summary>
        /// <param name="pcodigoCurso">Codigo del Curso, tipo String</param>
        /// <param name="pnombre">Nombre del Curso, tipo String</param>
        /// <param name="pdescripcion">Descripcion de curso, tipo String</param>
        /// <param name="pestado">Estado del curso, tipo Boolean</param>
        /// <remarks></remarks>
        internal  void registrarCursoPersistente(Cl_Curso pobjCurso, List<int> pcarreras, int pIdUsuario)
        {

            Parametros[] _params = new Parametros[3];

            String sql = @"insert into T_Curso (codigo_curso, nombre, descripcion)
                                values(param1, param2, param3)";

            //asignar para cada posición del arreglo(objeto, nombre)
            _params[0] = new Parametros(pobjCurso.codigoCurso, "param1");
            _params[1] = new Parametros(pobjCurso.nombre, "param2");
            _params[2] = new Parametros(pobjCurso.descripcion, "param3");
           

            try
            {
                //invocar y ejecutar...
              Int32 idCurso =  _acceso.executeSQLInsert(sql, _params);

                //registro bitacora
              Modulo.insertarBitacora(pIdUsuario, "Creación de un nuevo curso", idCurso, 4, 1);

                 //Registro de la asociacion de un carrera con un curso

                Parametros[] param = new Parametros[2];
                CursoPersistente persistenteCurso = new CursoPersistente();
                //Cl_Curso curso = new Cl_Curso();
                
                for (int i = 0; i < pcarreras.Count; i++)
                {
                    sql = @"insert into dbo.T_Curso_Carrera (id_curso, id_carrera)
                            values (param1, param2) ";

                    param[0] = new Parametros(idCurso, "param1");
                    param[1] = new Parametros(pcarreras[i], "param2");

                    //invocar y ejecutar...
                   int idRelacion = _acceso.executeSQLInsert(sql, param);

                    //registro bitacora
                   Modulo.insertarBitacora(pIdUsuario, "Creación de una nueva relacion carrera curso", idRelacion, 4, 1);
                }
            }
            catch (Exception ex)
            {
                SqlException exsql = ex as SqlException;
                SqlError er = exsql.Errors[0];

                if (er.Number == 2601)
                {
                    throw new Exception("Ya hay un curso con el mismo código.");
                }
                else
                {
                    throw new Exception("Ha habido un error al registrar el curso. ");
                }
            }
        }



        /// <summary>
        /// Método de la clase encargada de insertar un Cursos de forma masiva a la DB 
        /// </summary>
        /// <param name="listaCursos">Lista de cursos</param>
        /// <param name="pcarreras">Lista de codigo de carrera correspondiente</param>
        /// <remarks></remarks>
        internal void registrarCursoPersistenteBacth(List<Cl_Curso> listaCursos, List<int> pcarreras)
        {
            SqlConnection con = _acceso.GetConnection();
            con.Open();
            SqlTransaction tran = con.BeginTransaction();

            try{

            for (int j = 0; j < listaCursos.Count; j++)
            {


                Cl_Curso pobjCurso = listaCursos[j];
                Parametros[] _params = new Parametros[4];
                String sql = @"insert into T_Curso (codigo_curso, nombre, descripcion,estado)
                                values(param1, param2, param3, param4)";

                //asignar para cada posición del arreglo(objeto, nombre)
                _params[0] = new Parametros(pobjCurso.codigoCurso, "param1");
                _params[1] = new Parametros(pobjCurso.nombre, "param2");
                _params[2] = new Parametros(pobjCurso.descripcion, "param3");
                _params[3] = new Parametros(pobjCurso.estado, "param4");


                    //invocar y ejecutar...
                    Int32 idCurso = _acceso.executeSQLInsertTransation(tran, sql, _params);

                    //registro bitacora
                    Modulo.insertarBitacoraParaTransaccion (tran, 142, "Creación de un nuevo curso", idCurso, 4, 1);

                    //Registro de la asociacion de un carrera con un curso

                    Parametros[] param = new Parametros[2];
                    CursoPersistente persistenteCurso = new CursoPersistente();
                    //Cl_Curso curso = new Cl_Curso();


                    sql = @"insert into dbo.T_Curso_Carrera (id_carrera, id_curso)
                            values (param1, param2) ";

                    param[0] = new Parametros(pcarreras[j], "param1");
                    param[1] = new Parametros(idCurso, "param2");

                    //invocar y ejecutar...
                    _acceso.executeSQLInsertTransation(tran, sql, param);

                    //registro bitacora
                    Modulo.insertarBitacoraParaTransaccion(tran, 142, "Creación de una nueva relacion carrera curso", idCurso, 4, 1);

            }

            tran.Commit();
            }
            catch (Exception ex)
            {
                tran.Rollback();
                throw new System.Exception(ex.Message);
            }
            finally
            {
                con.Close();
            }
        }
      
        /// <summary>
        /// Método de la clase encargada de buscar un nuevo curso a la DB 
        /// </summary>
        /// <param name="pcriterio"></param>
        /// <remarks></remarks>
        /// <return>
        /// Retorna una lista generica de tipo curso
        /// </return>
        internal  List<Cl_Curso> buscarCursoPorCodigo(string pcriterio)
        {
            SqlDataReader _drCurso;

            String _sp = "sp_buscar_curso_codigo";

            List<Cl_Curso> _listaGenerica = new List<Cl_Curso>();

            Parametros[] _params = new Parametros[1];

            _params[0] = new Parametros(pcriterio, "codigo_curso");

            try
            {
                _drCurso = _acceso.execute_SP_Consulta(_sp, _params);

                while (_drCurso.Read())
                {
                    _listaGenerica.Add(new Cl_Curso(_drCurso.GetInt32(0), _drCurso.GetString(1), _drCurso.GetString(2), _drCurso.GetString(3)));
                }

                //retornar el resultado
                return _listaGenerica;
            }
            catch (Exception ex)
            {
                throw new Exception("Error al Buscar cursos... " + ex.Message);
            }
        }

        ///// <summary>
        ///// Método de la clase encargada de buscar un nuevo curso a la DB 
        ///// </summary>
        ///// <param name="pcriterio"></param>
        ///// <remarks></remarks>
        ///// <return>
        ///// Retorna una lista generica de tipo curso
        ///// </return>
        //internal List<Cl_Curso> buscarCursoPorCodigo()
        //{
        //    SqlDataReader _drCurso;
        //    Int32 criterio = 0;

        //    String _sp = "sp_listar_cursos";

        //    List<Cl_Curso> _listaGenerica = new List<Cl_Curso>();

        //    Parametros[] _params = new Parametros[1];

        //    _params[0] = new Parametros(criterio, "@id_curso");

        //    try
        //    {
        //        _drCurso = _acceso.execute_SP_Consulta(_sp, _params);

        //        while (_drCurso.Read())
        //        {
        //            _listaGenerica.Add(new Cl_Curso(_drCurso.GetInt32(0), _drCurso.GetString(1), _drCurso.GetString(2), _drCurso.GetString(3)));
        //        }

        //        //retornar el resultado
        //        return _listaGenerica;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw new Exception("Error al Buscar cursos... " + ex.Message);
        //    }
        //}

        /// <summary>
        /// Método de la clase encargada de buscar un nuevo curso a la DB 
        /// </summary>
        /// <param name="pcriterio"></param>
        /// <remarks></remarks>
        /// <return>
        /// Retorna una lista generica de tipo curso
        /// </return>
        internal  List<Cl_Curso> buscarCursoPorId(string pcriterio)
        {
            SqlDataReader _drCurso;

            String _sp = "sp_buscar_curso_id";

            List<Cl_Curso> _listaGenerica = new List<Cl_Curso>();

            Parametros[] _params = new Parametros[1];

            _params[0] = new Parametros(pcriterio, "id_curso");


            try
            {
                _drCurso = _acceso.execute_SP_Consulta(_sp, _params);

                while (_drCurso.Read())
                {
                    _listaGenerica.Add(new Cl_Curso(_drCurso.GetInt32(0), _drCurso.GetString(1), _drCurso.GetString(2)));
                }

                //retornar el resultado
                return _listaGenerica;
            }
            catch (Exception ex)
            {
                throw new Exception("Error al Buscar cursos... " + ex.Message);
            }
        }

        /// <summary>
        /// Método de la clase encargada de buscar un nuevo curso a la DB 
        /// </summary>
        /// <param name="pcriterio"></param>
        /// <remarks></remarks>
        /// <return>
        /// Retorna una lista generica de tipo curso
        /// </return>
        internal  List<Cl_Curso> buscarCursoPorNombre(string pcriterio)
        {
            SqlDataReader _drCurso;

            String _sp = "sp_buscar_curso_nombre";

            List<Cl_Curso> _listaGenerica = new List<Cl_Curso>();

            Parametros[] _params = new Parametros[1];

            _params[0] = new Parametros(pcriterio, "nombre");


            try
            {
                _drCurso = _acceso.execute_SP_Consulta(_sp, _params);

                while (_drCurso.Read())
                {
                    _listaGenerica.Add(new Cl_Curso(_drCurso.GetInt32(0), _drCurso.GetString(1), _drCurso.GetString(2), _drCurso.GetString(3)));
                }

                //retornar el resultado
                return _listaGenerica;

            }
            catch (Exception ex)
            {
                throw new Exception("Error al Buscar cursos... " + ex.Message);
            }
        }

        /// <summary>
        /// Método de la clase encargada de insertar un nuevo Curso a la DB 
        /// </summary>
        /// <param name="pcodigoCurso">Codigo del Curso, tipo String</param>
        /// <param name="pnombre">Nombre del Curso, tipo String</param>
        /// <param name="pdescripcion">Descripcion de curso, tipo String</param>
        /// <param name="pestado">Estado del curso, tipo Boolean</param>
        /// <remarks></remarks>
        internal void modificarCursoPersistente(Cl_Curso pobjCurso, List<int> pCarrerasA, Int32 pidUsuario)
        {

            // se crea la conexion de acceso a la base de datos.
            SqlConnection conexion = _acceso.GetConnection();
            //Se abre la conexion con la base de datos
            conexion.Open();
            // se crea un begin transacción para las sentencias que se van a generar, si alguna falla
            SqlTransaction transaction = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

            try
            {
                //Se crean los parámetros que se desean manejar en la sentencia SQL
                Parametros[] parametros = new Parametros[3];

                //Se genera la sentencia SQL a desarrollar 
                string sql = @"update dbo.T_Curso set codigo_curso = param1, nombre = param2, descripcion = param3";
                // se determinan los parámetros a enviar a la sentencia SQL

                parametros[0] = new Parametros(pobjCurso.codigoCurso, "param1");
                parametros[1] = new Parametros(pobjCurso.nombre, "param2");
                parametros[2] = new Parametros(pobjCurso.descripcion, "param3");

                // Actualiza las carreras 

                Parametros[] param = new Parametros[2];
                CursoPersistente persistenteCurso = new CursoPersistente();
                //Cl_Curso curso = new Cl_Curso();
                
                for (int i = 0; i < pCarrerasA.Count; i++)
                {
                 String  sql2 = @"update dbo.T_Curso_Carrera set  id_carrera = param1, id_curso = param2";
                           
                   
                    //param[0] = new Parametros(pCarrerasA[i], "param1");
                    //param[1] = new Parametros(, "param2");

                    //invocar y ejecutar...
                    _acceso.executeSQLInsert(sql2, param);
           
                //invocar y ejecutar...

                Int32 id = _acceso.executeSQLInsert(sql2, parametros);
                if (id != -1)
                {
                    Modulo.insertarBitacora(pidUsuario, "Modificación de un curso PWNED", id, 4, 3);
                }
                else
                {
                    throw new Exception("Ha habido un error al abrir el Periodo Lectivo.");
                }
            }
          }catch {
          
          } 
        }
        /// <summary>
        /// Método de la clase encargada de insertar una nueva Carrera a la BD
        /// </summary>
        /// <param name="pGrupo">Objeto carrera, tipo Carrera</param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        internal void eliminarCurso(String  pcodigo, int pIdUsuario)//parametros del grupo
        {

            Parametros[] parametros = new Parametros[1];
            String sql = "Delete T_Curso where codigo_curso = param1";

            parametros[0] = new Parametros(pcodigo, "param1");

            try
            {
                _acceso.executeSQL(sql, parametros);
                //BITACORA
                Modulo.insertarBitacora(pIdUsuario, "Eliminacion de un curso", 2, 3, 2);
                //------------
            }
            catch (Exception ex)
            {
                SqlException exsql = ex as SqlException;
                SqlError er = exsql.Errors[0];

                if (er.Number == 547)
                {
                    throw new Exception("Esta curso esta asociada a otras entidades así que no se puede borrar.");
                }
                else
                {
                    throw new Exception("Ha habido un error al eliminar la curso. " );
                }
            }

        }


        /// <summary>
        /// Método de la clase que busca los ids de las carreras de un estudiante.
        /// </summary>
        /// <param name="pIdGrupo">In del grupo, tipo int</param>
        /// <remarks></remarks>
        internal List<int> buscarIdsCursosDeCarrera(String pcodigoCarrera)
        {

            string psp = @"dbo.sp_buscar_ids_cursos";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pcodigoCarrera, "codigo_carrera");

            try
            {
                SqlDataReader reader = (SqlDataReader)_acceso.execute_SP_Consulta(psp, parametros);
                List<int> ids = new List<int>();
                while (reader.Read())
                {
                    ids.Add(reader.GetInt32(0));
                }

                reader.Close();
                return ids;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }


        /// <summary>
        /// Método de la clase que busca los ids de las carreras de un estudiante.
        /// </summary>
        /// <param name="pIdGrupo">In del grupo, tipo int</param>
        /// <remarks></remarks>
        internal List<int> buscarIdsCursosDeCurso(int pidCurso)
        {

            string psp = @"dbo.sp_buscar_ids_cursos";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pidCurso, "id_curso");

            try
            {
                SqlDataReader reader = (SqlDataReader)_acceso.execute_SP_Consulta(psp, parametros);
                List<int> ids = new List<int>();
                while (reader.Read())
                {
                    ids.Add(reader.GetInt32(0));
                }

                reader.Close();
                return ids;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }


        internal List<Cl_Curso> buscarCursosDeCarrera(String pcodigoCarrera)
        {

            string psp = @"dbo.sp_buscar_cursos_de_carrera";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pcodigoCarrera, "codigo_carrera");

            try
            {
                SqlDataReader reader = (SqlDataReader)_acceso.execute_SP_Consulta(psp, parametros);
                List<Cl_Curso> cursos = new List<Cl_Curso>();
                Cl_Curso curso = null;
                
                while (reader.Read())
                {
                    curso = new Cl_Curso();
                    curso.codigoCurso = reader.GetValue(0).ToString();
                    curso.nombre = reader.GetValue(1).ToString();
                    curso.descripcion= reader.GetValue(2).ToString();
                    curso.id = reader.GetInt32(3);
                    cursos.Add(curso);
                }

                reader.Close();
                return cursos;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }



        /// <summary>
        /// Método de la clase encargada de buscar los cursos de una carrera por su id
        /// </summary>
        /// <param name="pIdCarrera">Id de la carrera, tipo int</param>
        /// <remarks></remarks>
        internal List<Cl_Curso> buscarCursosDeCarrera(int pIdCarrera)
        {

            string psp = @"dbo.sp_buscar_cursos_de_carrera_por_id";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pIdCarrera, "idCarrera");

            try
            {
                SqlDataReader reader = (SqlDataReader)_acceso.execute_SP_Consulta(psp, parametros);
                List<Cl_Curso> cursos = new List<Cl_Curso>();
                Cl_Curso curso = null;

                while (reader.Read())
                {
                    curso = new Cl_Curso();
                    curso.id = reader.GetInt32(0);
                    curso.codigoCurso = reader.GetString(1);
                    curso.nombre = reader.GetString(2);               
                    cursos.Add(curso);
                }

                reader.Close();
                return cursos;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// Método de la clase que buscar todas las carreras del sistema.
        /// </summary>
        /// <remarks></remarks>
        public List<EsCurso> buscarTodosLosCursos()
        {
            string psp = @"dbo.sp_buscar_todos_los_cursos";
            List<EsCurso> cursos = new List<EsCurso>();

          
            try
            {
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, null);

                while (reader.Read())
                {
                    EsCurso temp = new EsCurso(reader.GetInt32(0) + "",
                                                     reader.GetString(1),
                                                    reader.GetString(2));
                    cursos.Add(temp);
                }

                reader.Close();
                return cursos;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }


        /// <summary>
        /// Método de la clase que buscar todas las carreras del sistema.
        /// </summary>
        /// <remarks></remarks>
        /// 
            internal List<Cl_Curso> buscarTodosCursos()
        {
            SqlDataReader _drCurso;

            int id = 1;

            String _sp = "sp_listar_cursos";

            List<Cl_Curso> _listaGenerica = new List<Cl_Curso>();

            Parametros[] _params = new Parametros[1];

            _params[0] = new Parametros(id, "id_curso");

            try
            {
                _drCurso = _acceso.execute_SP_Consulta(_sp, _params);

                while (_drCurso.Read())
                {
                    _listaGenerica.Add(new Cl_Curso(_drCurso.GetInt32(0), _drCurso.GetString(1), _drCurso.GetString(2), _drCurso.GetString(3), _drCurso.GetBoolean(4)));
                }

                //retornar el resultado
                return _listaGenerica;
            }
            catch (Exception ex)
            {
                throw new Exception("Error al Buscar Temas... " + ex.Message);
            }
        }


            public List<EsCurso> listarLosCursos()
            {
                string psp = @"dbo.sp_buscar_todos_los_cursos";

                List<EsCurso> cursos = new List<EsCurso>();


                try
                {
                    SqlDataReader reader = _acceso.execute_SP_Consulta(psp, null);

                    while (reader.Read())
                    {
                        EsCurso temp = new EsCurso(reader.GetInt32(0) + "",
                                                         reader.GetString(1),
                                                        reader.GetString(2));
                        cursos.Add(temp);
                    }

                    reader.Close();
                    return cursos;

                }
                catch (Exception ex)
                {
                    throw ex;
                }

            }




        public List<EsCurso> buscarCursosAsociadosCarrera(int pidCarrera)
        {
            string psp = @"dbo.sp_listar_cursos_carrera";
            List<EsCurso> cursos = new List<EsCurso>();

            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pidCarrera, "id_carrera");

            try
            {
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, parametros);

                while (reader.Read())
                {
                    EsCurso temp = new EsCurso(reader.GetInt32(0) + "",
                                                    reader.GetString(1),
                                                    reader.GetString(2));
                    cursos.Add(temp);
                }

                reader.Close();
                return cursos;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        internal void actualizarCursos(Cl_Curso pobjCurso, List<int> listaCarreraA, List<int> pIdsBD, int pid,int pidUsuario)
        {
            SqlConnection conexion = _acceso.GetConnection();
            conexion.Open();
            SqlTransaction transaction = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

            try
            {

                Parametros[] parametros = new Parametros[4];

                string sql = @"update dbo.T_Curso set codigo_curso = param1, nombre = param2, descripcion = param3 where id_curso = param0 ";

                parametros[0] = new Parametros(pid, "param0");
                parametros[1] = new Parametros(pobjCurso.codigoCurso, "param1");
                parametros[2] = new Parametros(pobjCurso.nombre, "param2");
                parametros[3] = new Parametros(pobjCurso.descripcion, "param3");
                

                    _acceso.executeSQL(sql, parametros);

                    string sqlUpdate = "delete dbo.T_Curso_Carrera" +
                                        " where  id_curso = param1 and" +
                                        " id_carrera = param2 ";                      
                                    

                    string sqlInsert = "insert into dbo.T_Curso_Carrera(id_curso,id_carrera)" +
                                        " values(param1, param2)";

                    EsBitacora bitacora = new EsBitacora();
                    bitacora.IdUsuario = pidUsuario;
                    bitacora.Descripcion = "Cambio de carrera de un curso";
                    bitacora.Tipo = "4";


                    Parametros[] paramUpdate = new Parametros[2];
                    paramUpdate[0] = new Parametros(pid, "param1");
                    paramUpdate[1] = new Parametros("", "param2");

                
                    Parametros[] paramInsert = new Parametros[2];
                    paramInsert[0] = new Parametros(pid, "param1");
                    paramInsert[1] = new Parametros("", "param2");
             
                    Modulo.comparaListas(listaCarreraA, pIdsBD, sqlUpdate, sqlInsert, paramUpdate, paramInsert, bitacora, null);


                transaction.Commit();
                conexion.Close();
            }
            catch (Exception)
            {
                
                try
                {
                    transaction.Rollback();
                }
                catch (Exception)
                {
                    
                    throw new Exception("Hubo un error al intentar modificar el curso. el curso no ha sido modificada.");

                }        
            }
            finally
            {
                conexion.Close();
            }

        }
    }
}